﻿using System;
using System.Collections.Generic;
using System.Linq;

using SharedGenomics.Core;

namespace SharedGenomics.Workbench.Annotations
{
    public class AnnotationRequestStatusNotifier : IAnnotationRequestStatusNotifier
    {
        private IDictionary<object, HashSet<WeakReference>> _notifiables;
        private object _lock = new object();

        public AnnotationRequestStatusNotifier()
        {
            this._notifiables = new Dictionary<object, HashSet<WeakReference>>();
        }

        public void RequestCompleted(AnnotationRequestResult result)
        {
            if (result != null)
            {
                lock (this._lock)
                {
                    HashSet<WeakReference> targetNotifiables;
                    if (this._notifiables.TryGetValue(result.RootValue, out targetNotifiables))
                    {
                        //get the alive notifiables for the result's annotation target and notify them of the result
                        var aliveNotifiables = targetNotifiables.Where(wr => wr.IsAlive).Select(wr => wr.Target).Cast<IAnnotationRequestStatusNotifiable>();
                        aliveNotifiables.ForEach(n =>
                        {
                            n.Notify(result);
                        });
                    }
                }
            }
        }

        public void AddNotificationFor(IAnnotationRequestStatusNotifiable notifiable)
        {
            notifiable.ThrowIfNull("notifiable");
            ExceptionHelper.ThrowIf<ArgumentException>(notifiable.AnnotationTarget == null, "Notifiable must have a non-null annotation target");

            WeakReference notifiableRef = new WeakReference(notifiable);

            lock (this._lock)
            {
                var targetSet = this._notifiables.GetValueForSafe(notifiable.AnnotationTarget, () => new HashSet<WeakReference>());
                targetSet.Add(notifiableRef);
            }
        }

        public void RemoveNotificationFor(IAnnotationRequestStatusNotifiable notifiable)
        {
            throw new NotImplementedException();
        }

        public void ClearNotifications()
        {
            lock (this._lock)
            {
                this._notifiables.Clear();
            }
        }
    }
}
